package middleware

import (
	"errors"
	"log"
	"net/http"
	"time"

	"tiktok2023/model"

	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
)

var jwtKey = []byte("tiktok")

type MyClaims struct {
	UserId uint64
	jwt.StandardClaims
}

// 判断是否登录
func IsLogin() gin.HandlerFunc {
	return func(context *gin.Context) {
		// auth := context.Query("token")

		var auth string

		// 检查请求 Body 中是否有 token 参数
		if token := context.PostForm("token"); token != "" {
			auth = token
		} else {
			// 如果请求 Body 中没有 token 参数，则从查询参数中获取
			auth = context.Query("token")
		}

		if len(auth) == 0 {
			context.Abort()
			context.JSON(http.StatusUnauthorized, model.Response{
				StatusCode: 1,
				StatusMsg:  "not login",
			})
		}
		token, err := ParseToken(auth)
		if err != nil {
			context.Abort()
			context.JSON(http.StatusUnauthorized, model.Response{
				StatusCode: 1,
				StatusMsg:  "not login",
			})
		}

		if token == nil {
			log.Println("Token is nil")
			context.Abort()
			context.JSON(http.StatusUnauthorized, model.Response{
				StatusCode: 1,
				StatusMsg:  "not login",
			})
		} else {
			log.Printf("Token UserId: %d", token.UserId)
		}

		context.Set("userId", token.UserId)
		context.Next()
	}
}

// 鉴定权限,未登录状态，若携带token，则解析出userid，未携带则为0
func NotLoginWithToken() gin.HandlerFunc {
	return func(context *gin.Context) {
		auth := context.Query("token")
		var userId uint64
		if len(auth) == 0 {
			userId = 0
		} else {
			token, err := ParseToken(auth)
			if err != nil {
				context.Abort()
				context.JSON(http.StatusUnauthorized, model.Response{
					StatusCode: 1,
					StatusMsg:  "Token Error",
				})
			} else {
				userId = token.UserId
			}
		}
		context.Set("userId", userId)
		context.Next()
	}
}

// 生成token
func GenerateToken(userId uint64) (string, error) {
	//过期时间设定为2小时
	expiresationtime := time.Now().Add(2 * time.Hour)
	claims := MyClaims{
		UserId: userId,
		StandardClaims: jwt.StandardClaims{
			ExpiresAt: expiresationtime.Unix(),
			IssuedAt:  time.Now().Unix(),
			Issuer:    "lls",
			Subject:   "user token",
		},
	}

	//创建新的声明
	tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	tokenstr, err := tokenClaims.SignedString(jwtKey)
	if err != nil {
		return "", err
	}
	return tokenstr, nil
}

// 解析token
func ParseToken(tokenstr string) (*MyClaims, error) {
	claims := MyClaims{}
	token, err := jwt.ParseWithClaims(tokenstr, &claims, func(token *jwt.Token) (interface{}, error) {
		return jwtKey, nil
	})
	if err != nil {
		return nil, err
	}
	//如果token无效
	if !token.Valid {
		return nil, errors.New("the token is invalid")
	}
	return &claims, nil
}
